#ifndef CKKS_SRC_BOOTSTRAPPING_BOOTSTRAPPING_H
#define CKKS_SRC_BOOTSTRAPPING_BOOTSTRAPPING_H

#include "homomorphic_mod.h"
#include "cosine_approx.h"
#include "homomorphic_encoding.h"
#include "../string_utils.h"

struct longDiv {
    std::vector<double> q;
    std::vector<double> r;

    longDiv() = default;
    longDiv(const std::vector<double> &q0, const std::vector<double> &r0) : q(q0), r(r0) {}
};


class Bootstrapper {
public:
    Context &context;
    SecretKey &secretKey;
    Scheme &scheme;

    // -----------------evalmod参数--------------------
    EvalModPoly &evalModPoly;

    EncodingMatrix &encodingMatrix;

    uint64_t Q;
    int levelStart;
    __uint128_t scalingFactor;
    SineType sineType;
    double messageRatio;
    int k;
    int sineDeg;
    int doubleAngle;
    int arcSineDeg;

    vector<Ciphertext *> evalSinePolyPool; // chebyshev基
    vector<Ciphertext> evalBasis;
    vector<Polynomial *> chebyshevPolyCoeffTreePool; // chebyshev系数（最下层16~31有用）
    vector<Ciphertext *> chebyshevTreePool;          // 存放每一个chebyshev节点的值
    // -----------------evalmod参数--------------------


    // 初始化构造函数
    Bootstrapper(Context &context, Scheme &scheme, SecretKey &secretKey1, EvalModPoly &evalModPoly, EncodingMatrix &encodingMatrix);
    // 拷贝构造函数
    Bootstrapper(const Bootstrapper &cipher) = delete;
    Bootstrapper &operator = (const Bootstrapper &o) = delete;
    // 移动构造函数
    Bootstrapper(Bootstrapper &&other) = delete;
    Bootstrapper &operator = (Bootstrapper &&other) = delete;

    void BootStrapping(Ciphertext& cipher);

    // -----------------evalmod函数--------------------
    // 分割系数函数
    void SplitCoeffsPolyVector(int split, vector<Polynomial *> chebyshev_coeff_tree_pool, int tree_idx);
    // 计算树最底层的叶子节点系数
    void PrepareChebyshevCoeffsTree(int logSplit, int logDegree, int tree_idx);
    // 预计算树的系数数组——使用提前准备的系数计算
    void PrepareSineChebyshevPoly();
    // 预计算树的系数数组--与计算系数的函数结合
    void PrepareSineChebyshevPolyEval(EvalModPoly evalModPolyPre);
    // 计算基的函数
    void ComputeChebyshevBasis(Ciphertext &ct0, SecretKey &secretKeyCom);
    // 迭代计算整个chebyshev多项式的函数
    void EvalIteration(__uint128_t target_scale, SecretKey &secretKeyEval);
    // evalmod主函数
    void EvalMod(Ciphertext &ct0);
    // -----------------evalmod函数--------------------


    Ciphertext EvalChebyshevSeriesPS(Ciphertext x, const std::vector<double> &coefficients, double a, double b);

    Ciphertext InnerEvalChebyshevPS(Ciphertext x, const std::vector<double> &coefficients, uint32_t kInner, uint32_t m,
                                    std::vector<Ciphertext> &T, std::vector<Ciphertext> &T2);

    uint32_t Degree(const std::vector<double> &coefficients);

    std::vector<uint32_t> PopulateParameterPS(const uint32_t upperBoundDegree);

    std::vector<uint32_t> ComputeDegreesPS(const uint32_t n);

    longDiv LongDivisionChebyshev(const std::vector<double> &f, const std::vector<double> &g);

    Ciphertext EvalLinearWSumMutable(std::vector<Ciphertext> &ciphertexts, const std::vector<double> &constants);

    void AdjustLevelsAndDepthInPlace(Ciphertext &ciphertext1, Ciphertext &ciphertext2);

    void ApplyDoubleAngleIterations(Ciphertext &ciphertext, uint32_t numIter);
};

// Chebyshev series coefficients for the SPARSE case
static const std::vector<double> gCoefficientsSparse{
        -0.18646470117093214,   0.036680543700430925,    -0.20323558926782626,     0.029327390306199311,
        -0.24346234149506416,   0.011710240188138248,    -0.27023281815251715,     -0.017621188001030602,
        -0.21383614034992021,   -0.048567932060728937,   -0.013982336571484519,    -0.051097367628344978,
        0.24300487324019346,    0.0016547743046161035,   0.23316923792642233,      0.060707936480887646,
        -0.18317928363421143,   0.0076878773048247966,   -0.24293447776635235,     -0.071417413140564698,
        0.37747441314067182,    0.065154496937795681,    -0.24810721693607704,     -0.033588418808958603,
        0.10510660697380972,    0.012045222815124426,    -0.032574751830745423,    -0.0032761730196023873,
        0.0078689491066424744,  0.00070965574480802061,  -0.0015405394287521192,   -0.00012640521062948649,
        0.00025108496615830787, 0.000018944629154033562, -0.000034753284216308228, -2.4309868106111825e-6,
        4.1486274737866247e-6,  2.7079833113674568e-7,   -4.3245388569898879e-7,   -2.6482744214856919e-8,
        3.9770028771436554e-8,  2.2951153557906580e-9,   -3.2556026220554990e-9,   -1.7691071323926939e-10,
        2.5459052150406730e-10
};


#endif // CKKS_BOOTSTRAPPING_H
